import * as vscode from "vscode";
import { Box3Get, Box3Put, escapeHtml } from "@ap/util/request";
import {
  showErrorMessage,
  showInformationMessage,
} from "@ap/util/vscode/message";
import { updatePackageJson, getPackageJson } from "@ap/util/packageJson";
import { PackageConfig } from "@ap/types/config";
import { storageMap } from "@ap/command";

// 动态数据表数据
export let data: ExtendedQuickPickItem[];

// 数据空间数据
export let storageData: Record<string, any>;

export interface DataItem {
  storageName: string;
  isGroup: boolean;
  offset: number;
  constraint: {
    target?: string;
    ascending?: boolean;
    max?: number;
    min?: number;
  };
}
// 当前数据表配置数据
export let getDataConfig: DataItem;
// 当前数据表总长度
export let getDataCount: number;

interface Item {
  [key: string]: any;
}
export function setDataCount(n: number) {
  getDataCount = n;
}

export interface ExtendedQuickPickItem extends vscode.QuickPickItem {
  key: string;
}
/**
 * 异步获取数据空间表分页查询数组。
 * @returns 返回承诺，解析为数据项数组。
 */
export async function getMapStorageList(
  prop?: DataItem,
): Promise<ExtendedQuickPickItem[] | undefined> {
  return getPackageJson<PackageConfig>("map").then(async (packageJson) => {
    if (packageJson) {
      const mapId = packageJson.id;
      if (mapId) {
        prop ? (getDataConfig = prop) : undefined;
        const requestOptions = {
          url:
            "open/storage/page?mapId=" +
            mapId +
            "&storageName=" +
            getDataConfig.storageName +
            "&constraint.ascending=" +
            (getDataConfig.constraint?.ascending ?? "") +
            "&constraint.max=" +
            (getDataConfig.constraint?.max ?? "") +
            "&constraint.min=" +
            (getDataConfig.constraint?.min ?? "") +
            "&constraint.target=" +
            (getDataConfig.constraint?.target ?? "") +
            "&isGroup=" +
            getDataConfig.isGroup +
            "&limit=50&offset=" +
            getDataConfig.offset,
        };
        /**
         * 发送请求并等待响应。
         */
        const response = await Box3Get(requestOptions, "地图数据空间");
        /**
         * 检查响应是否成功，如果不成功则返回错误消息。
         */
        if (!response || response.code !== 200) {
          showErrorMessage(`获取地图数据空间失败: ${response.msg}`);
          return;
        }
        storageData = convertToJson(response.data);
        getDataCount = response.data.count;

        let pageCount = getDataConfig.offset + 1;
        storageMap.description = `${getDataConfig.storageName} | 第${pageCount}-${getDataConfig.offset + 50}项 | 共${getDataCount}项`;

        /**+
         * 处理响应数据，映射物品到数据项格式，并转义HTML字符以防止XSS攻击。
         */
        const dataSource: ExtendedQuickPickItem[] = response.data.rows.map(
          (item: Item, index: number) => ({
            label: `${pageCount + index} - ${item.key}`,
            key: `${item.key}`,
            description:
              typeof validJson(JSON.parse(item.value).content) +
              " | " +
              convertTimestampToDateString(item.updateTime),
            detail: stringifyIfObject(JSON.parse(item.value).content),
          }),
        );
        console.log(dataSource);
        if (!response.data.count) {
          dataSource.push({
            label: `当前空间暂无数据，请点击 + 新增数据`,
            key: ``,
            description: "",
            detail: "",
          });
        }
        data = dataSource;
        return dataSource;
      }
    }
  });
}

/**
 * 异步获取数据空间值查询。
 * @returns 返回承诺，解析为数据项。
 */
export async function getMapStorage(prop: {
  key: string;
}): Promise<Record<string, any> | undefined> {
  return getPackageJson<PackageConfig>("map").then(async (packageJson) => {
    if (packageJson) {
      const mapId = packageJson.id;
      if (mapId) {
        const requestOptions = {
          url:
            "open/storage?mapId=" +
            mapId +
            "&storageName=" +
            getDataConfig.storageName +
            "&key=" +
            prop.key +
            "&isGroup=" +
            getDataConfig.isGroup,
        };

        /**
         * 发送请求并等待响应。
         */
        const response = await Box3Get(requestOptions, "地图数据空间值");
        /**
         * 检查响应是否成功，如果不成功则返回错误消息。
         */
        if (!response || response.code !== 200) {
          showErrorMessage(`获取地图数据空间值失败: ${response.msg}`);
          return;
        }
        return response;
      }
    }
  });
}

export function convertTimestampToDateString(timestamp: number): string {
  const date = new Date(timestamp);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  const seconds = String(date.getSeconds()).padStart(2, "0");

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

function stringifyIfObject(value: any) {
  if (typeof value === "object" && value !== null) {
    return JSON.stringify(value);
  }
  return value;
}

export function isValidJson(jsonString: any) {
  try {
    if (jsonString.includes("{") && jsonString.includes("}")) {
      JSON.parse(jsonString.replace(/\s+/g, ""));
      return true;
    }
    return false;
  } catch (e) {
    return false;
  }
}

export function validJson(jsonString: any) {
  try {
    return JSON.parse(jsonString.replace(/\s+/g, ""));
  } catch (e) {
    return jsonString;
  }
}

function convertToJson(value: Record<string, any>) {
  const data: Record<string, any> = {};
  const dataSource: Record<string, any> = value.rows.map(
    (item: Item, index: number) => ({
      key: item.key,
      value: validJson(JSON.parse(item.value).content),
      createTime: convertTimestampToDateString(item.createTime),
      updateTime: convertTimestampToDateString(item.updateTime),
    }),
  );
  data["rows"] = dataSource;
  data["count"] = value.count;
  return data;
}
